package com.soup.lab.basic.iso;

import com.soup.lab.basic.iso.executor.KeyPickRunnable;

import java.util.Collection;
import java.util.Set;

public class TaskQueue<T> {

    private Set<T> runningKeys;
    private Set<T> waitingKeys;


    private void addRunningKeys(Collection<T> keys) {
        runningKeys.addAll(keys);
    }

    private void removeRunningKeys(Collection<T> keys) {
        runningKeys.removeAll(keys);
    }

    private void addWaitingKeys(Collection<T> keys) {
        waitingKeys.addAll(keys);
    }

    private void removeWaitingKeys(Collection<T> keys) {
        waitingKeys.removeAll(keys);
    }


    static class TaskNode {

    }

    interface ExecNode<T> {
        Collection<T> keys();
        void execute();
    }

    static abstract class AbstractExecNode<T> implements ExecNode<T> {

        private final Runnable runnable;

        public AbstractExecNode(Runnable runnable) {
            this.runnable = runnable;
        }

        @Override
        public void execute() {
            beforeExec();
            try {
                runnable.run();
            } finally {
                afterExec();
            }
        }

        protected void beforeExec(){}

        protected void afterExec(){}

    }

    static class QueuedExecNode<T> extends AbstractExecNode<T> {

        private final KeyPickRunnable<T> keyPickRunnable;
        private final TaskQueue<T> taskQueue;

        public QueuedExecNode(KeyPickRunnable<T> runnable, TaskQueue<T> taskQueue) {
            super(runnable);
            this.keyPickRunnable = runnable;
            this.taskQueue = taskQueue;
        }

        @Override
        public Collection<T> keys() {
            return keyPickRunnable.getKeys();
        }

        @Override
        protected void beforeExec() {
            super.beforeExec();
        }

        @Override
        protected void afterExec() {

            super.afterExec();
        }
    }


    /**
     * 执行包，里面会有多个有序的执行节点
     */
    interface ExecPack<T> {
        boolean accept(ExecNode<T> node);
        boolean hasElement();
        ExecNode<T> pullFirst();
        boolean pushNode(ExecNode<T> node);
    }


}
